    /**
<p>This class is an extension of FMXISRoundDial that provides round dial functionality
with a rate-limited needle (based on a user-specified needle rate).  Developers can set its
value in two ways.  First, by setting the <code>val</code> property to have the
dial jump immediately to that value.  Second, by setting the <code>targVal</code>
property, the dial will reach the target value based on the set needle rate (<code>needleRate</code>).
For convenience, the gauge generates an event, <code>onReachTarg</code> when it reaches the target value (only if
set using <code>targVal</code>).</p>

<p>To simulate the smooth needle movement, this component updates the needle approximately every
1/20th of a second (note: because it uses Flash's <code>setInterval()</code> this interval can be up to twice as slow if the
frame rate is set around 20 fps, due to "features" of the setInterval implementation).  Therefore,
if you have more than a few of these components on the stage, you may find that it slows down other processes.  If
you need many of these on the Stage at once, you might consider rewriting this to centralize the needle update and
need for all the timers.</p>

<p>Users can change the appearance of the
hand by modifying: <code>defRndDialHand</code>, 
center of the dial by modifying: <code>defRndDialCenter</code>,
the background graphic by modifying: <code>defRndDialBkgnd</code>.</p>

<p>Showing the dial center and background are optional.</p>
 
<p>This class inherits from <code>FMXISRoundDial</code> to provide the base gauge functionality.</p>

@class FMXISRoundDialSmooth
@codehint _rdialSmooth
@author Jonathan Kaye (FlashSim.com)
@tooltip Round dial (gauge) with rate-limited needle transition
*/
/*
This code was developed by Jonathan Kaye and Amethyst Interactive LLC,
Copyright 2002-2004, all rights reserved.
v2.0, February, 2004
*/
import mx.core.UIObject;
import mx.fmxis.FMXISRoundDial;


[IconFile("rdial.png")]


[Event("onTargReach")]

/**
Event generated when the needle reaches the target value (only after target value has been
set using the <code>targVal</code> property).

@event onReachTarg
*/

class mx.fmxis.FMXISRoundDialSmooth extends FMXISRoundDial {
	
	var className:String = "FMXISRoundDialSmooth";
	static var symbolOwner:Object = FMXISRoundDialSmooth;
	static var symbolName:String = "FMXISRoundDialSmooth";
	
/**
Property that holds the string name of the event generated by this component.  This must
be set through the component property panel or programmatically
through the initObject parameter of attachMovie/createClassObject.
@property evtReachTarg
*/
	[Inspectable(name="onReachTarg method name", type=String, defaultValue="onReachTarg")]
	private var evtReachTarg:String;
	
/**
The rate the needle travels when the gauge is set using <code>targVal</code> property.  The
rate is in units per second.  You can change this property to change the rate, but not during
needle movement (in that case, use <code>setVal()</code> to fix the needle position, adjust
the rate, and set the new target rate).
@property needleRate
*/
	[Inspectable(name="Needle rate (units/sec)", type=Number, defaultValue=10)]
	private var needleRate:Number;
	
	public function set targVal (v:Number) {
		v = v % units;
		
		setTargVal(v);
		_targVal = v;
	}
	public function get targVal () {
		return _targVal;
	}
	private var _targVal:Number;
	private var _unitsPupd:Number; // units per update
	private var _inX:Boolean; // whether or not currently transitioning
	private var _xID:Number; // ID for setInterval during needle transition
	
	// clipParameters - for backward compatibility with Flash 6 player
	var clipParameters:Object = { units:1, showBack:1, centerVis:1, nXScale:1,
								nYScale:1, val:1, bkgndLinkID:1, centerLinkID:1, needleLinkID:1, needleRate:1 };
	private static var mergedClipParameters:Boolean = UIObject.mergeClipParameters(FMXISRoundDialSmooth.prototype.clipParameters, 
                               UIObject.prototype.clipParameters);

									
	static var dialEvents:Array = new Array("onReachTarg");
	
	// by default, use the event names as given by dialEvents.  We made it a static
	// variable for space efficiency.
	private var myEvents:Array = dialEvents;
	
	
	// constructor
	function FMXISRoundDialSmooth () {
	}
		
	private function init (evts): Void {
		// if the user has changed any event names, make sure named listeners are handled
		if (myEvents[0] != evtReachTarg  ||
		    evts != null) {
			this.myEvents = [ evtReachTarg ];
		}
		if (evts != null) {
			if (!(evts instanceof Array)) {
				evts = [ evts ];
			}
			
			super.init(myEvents = myEvents.concat(evts));
			
		} else {
			super.init(myEvents);
		}
	}
	
	function setTargVal (v) {
		_unitsPupd = needleRate / 20;
		if (v < _val) 
			_unitsPupd *= -1;

		if (!_inX && v != _val) {
			_xID = setInterval(this, "xCbk", 50);
			_inX = true;
		}
		_targVal = v;
	}
	
/**
Used as callback to update the needle based on increment appropriate for set needle speed.
@method xCbk
@access private
*/
	private function xCbk () {
		var x = _val + _unitsPupd, diff;
		
		diff = Math.abs(x - _targVal);
		if (diff < Math.abs(_unitsPupd)) {
			clearInterval(_xID);
			_inX = false;
			x = _val = _targVal;
			
			this.eventObj.type = evtReachTarg;
			this.eventObj.val = x;
			dispatchEvent(this.eventObj);
		}
		
		setNeedle(x);
		_val = x;
	}
	
	public function set val (v:Number) {
		if (_inX) {
			clearInterval(_xID);
			_inX = false;
			_targVal = v;
		}
		setNeedle(v);
		_val = v;
	}
}

/**
This property gives the linkage ID of the background to use instead of the default graphic
in the Library. This must
be set through the component property panel or programmatically
through the initObject parameter of attachMovie/createClassObject.
@property bkgndLinkID
*/
	
/**
This property gives the linkage ID of the center overlay graphic to use instead of the default graphic
in the Library. This must
be set through the component property panel or programmatically
through the initObject parameter of attachMovie/createClassObject.
@property centerLinkID
*/
	
/**
This property gives the linkage ID of the graphic to use instead of the default needle graphic
in the Library.  This must
be set through the component property panel or programmatically
through the initObject parameter of attachMovie/createClassObject.

@property needleLinkID
*/

/**
Current value of the dial (where needle is set).  Set this property to change the displayed
value immediately.
@property val
*/
	
/**
Scaling factor along the x axis (width) for the needle.

@property nXScale
*/
/**
Scaling factor along the y axis (height) for the needle.

@property nYScale
*/

/**
Boolean property indicating whether the center graphic is visible (true) or not (false).
@property centerVis
*/
	
/**
Boolean property indicating whether the background graphic is visible (true) or not (false).

@property showBack
*/

/**
Number of units in a full cycle for the dial.
@property units
*/

/**
Sets the number of units in a full cycle

@method setNumUnits
@param v Number of units
*/

/**
This method allows the developer to register a listener object to receive event notification
for the specific event, given by name.  This method is provided by mx.events.EventDispatcher.

@method addEventListener
@param eventName String name of the event to listen for
@param inst Listener instance
*/

/**
This method removes the listener specified from those notified when the specified event is generated.
This method is provided by mx.events.EventDispatcher.

@method removeEventListener
@param eventName String name of the event to listen for
@param inst Listener instance
*/

/**
<p>The listener property is designed for convenience at component instantiation time.  It is
the string name of a listener to register on this component.  Developers can certainly register
listeners programmatically through <code>addListener()</code> or <code>addEventListener()</code>,
but this property makes it convenient to add the first listener -- in many cases, there is only one.</p>

<p>FMXISBase simply takes this property at initialization time and calls <code>addProxyListener()</code>.
Therefore, developers can also prefix the name by a relative (e.g., _parent) or absolute (e.g., _root,
_level, or _global) path.</p>
	
@property listener
*/

/**
Register the listener programmatically to receive <b>all</b> events for this component.
We can accept the listener if it is an instance name (use addEventListener directly)
or the string name of the listener (then we add a proxy listener).
	
@method addListener
@param lstner The listener's instance or string name (with or without relative or absolute path)
*/
	
/**
Remove the listener from this component's event notification list.  Inside, we see if the listener specified
is an instance or a string, then call the appropriate removal routine to clean up.
@method removeListener
@param lstnr
*/

/**
This adds a listener instance name (string) to the list of listeners.  The name
may carry a relative or absolute path (_parent, _level, _global, etc.). If evts
is undefined, use the existing list of events for this component (from myEvents,
which subclasses that have events must override).  If evts is not undefined, then
it is an array containing elements that are event names (strings) for each event
that the listener wants to hear.

@method addProxyListener
@param listenerName String name of the listener instance
@param evts Array of events to register listener for, leave undefined for all component events
*/

/**
Removes the given listener (listenerName, a) from our records, and event notification.  If
the listener was added with a relative or absolute path, then it must be removed with a path
that gets to the correct timeline as well, even if that prefix is different from when the listener
was added (for example, if the handler removing the listener is on a different timeline than the
one that added the listener).

@method removeProxyListener
@param listenerName Listener instance name (string)
*/
